﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using T.FAS.Runtime.Action.SPI;

namespace T.FAS.Runtime.Action.Engine
{
    /// <summary>
    /// SG服务执行代理，与具体的SG站点打交道
    /// </summary>
    internal class HttpInovker
    {
        public HttpInovker()
        {
        }
        /// <summary>
        /// 向指定URL起Post调用，超时时间默认10分钟
        /// </summary>
        /// <param name="dataCenterId"></param>
        /// <param name="serviceId"></param>
        /// <param name="parameter"></param>
        /// <param name="timeoutMinitues"></param>
        /// <returns></returns>
        internal AppDebugResponse Post(string address,Dictionary<string,object> parameter,int timeoutMinitues = 10)
        {
            ServicePointManager.DefaultConnectionLimit = 2048;
            AppDebugResponse response = new AppDebugResponse();

            try
            {
                var request = (HttpWebRequest)WebRequest.Create(address);
                request.Timeout = timeoutMinitues * 600 *1000;//默认超时时间10分钟
                if (parameter == null)
                    parameter = new Dictionary<string, object>();
                if (parameter.ContainsKey(ActionRTPConst.DevAppIDKey))
                {
                    request.Headers.Add(ActionRTPConst.DevAppIDKey,Convert.ToString(parameter[ActionRTPConst.DevAppIDKey]));
                }
                var parameterJson = JsonConvert.SerializeObject(parameter);
                request.Method = "POST";
                request.ContentType = "application/json";

                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write(parameterJson);
                    streamWriter.Flush();
                    streamWriter.Close();
                }

                using (var httpResponse = (HttpWebResponse)request.GetResponse())
                {
                    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                    {
                        var result = streamReader.ReadToEnd();
                        if (httpResponse != null) httpResponse.Close(); 
                        object returnState = "1";
                        object returnErrorMessage = "";
                        response.state = Convert.ToString(returnState);
                        response.data = result;
                        response.errmsg = Convert.ToString(returnErrorMessage);
                    }
                }
            }

            catch (Exception e)
            {
                response.state = "0";
                response.errmsg = $"访问{address}发生异常，{WrapResponseException(e)}";
            }

            return response;
        }

        private string WrapResponseException(Exception e)
        {
            var srvExceptionMessage = string.Empty;
            if (e is WebException)
            {
                #region WebException异常
                var webException = e as WebException;

                if (webException.Response != null)
                {
                    #region 服务端有响应返回
                    //Protocal Error
                    var httpWebResponse = webException.Response as HttpWebResponse;

                    //获取服务端具体的异常信息
                    using (var streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
                    {
                        srvExceptionMessage = streamReader.ReadToEnd();
                    }

                    var responseStatusCode = (int)httpWebResponse.StatusCode;
                    return $"服务端异常编号：{responseStatusCode}，异常信息：{srvExceptionMessage}";
                    #endregion
                }
                else
                {
                    #region Response=null的服务端无响应返回，操作超时异常在这里
                    var clientStatusCode = (int)webException.Status > 9 ? Convert.ToString((int)webException.Status) : "0" + Convert.ToString((int)webException.Status);
                    return $"请求异常编号：{clientStatusCode}，异常信息：{GetExceptionStackInfo(e)}";
                    #endregion
                }
                #endregion
            }
            else
            {
                # region 非WebException异常
                return $"异常信息：{GetExceptionStackInfo(e)}";
                #endregion
            }
        }

        /// <summary>
        /// 获取完整异常堆栈信息
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        private string GetExceptionStackInfo(Exception ex)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Exception Stack:");
            sb.AppendLine(ex.StackTrace);
            var inner = ex.InnerException;
            while (inner != null)
            {
                sb.AppendLine("InnerException Message:" + inner.Message);
                sb.AppendLine("InnerException Stack:" + inner.StackTrace);
                inner = inner.InnerException;
            }
            return sb.ToString();
        }
    }
}
